﻿using PLCS.Application.Contracts.ProcessApp.Dtos;
using PLCS.Application.Contracts.SolutionApp;
using PLCS.Application.Contracts.SolutionApp.Dtos;
using PLCS.Domain.Processes;
using PLCS.Domain.Solutions;
using PLCS.Shared.Common.Constant;

using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories;

namespace PLCS.Application.SolutionApp
{
    public class SolutionAppService : CrudAppService<Solution, SolutionDto, Guid, PagedResultRequestDto, SolutionEditDto>, ISolutionAppService
    {
        private readonly ISolutionRepository _solutionRepository;
        private readonly IProcessRepository _processRepository;
        private readonly IRepository<SolutionStep, Guid> _solutionStepRepository;

        public SolutionAppService(
            ISolutionRepository solutionRepository,
            IProcessRepository processRepository,
            IRepository<SolutionStep, Guid> solutionStepRepository) : base(solutionRepository)
        {
            _solutionRepository = solutionRepository;
            _processRepository = processRepository;
            _solutionStepRepository = solutionStepRepository;
        }

        public override async Task<SolutionDto> CreateAsync(SolutionEditDto input)
        {
            var solution = new Solution(input.SolutionNo, input.SolutionName);
            foreach (var item in input.SolutionSteps)
            {
                var step = await _solutionRepository.FindSolutionStepAsync(x => x.StepNo == item.StepNo && x.StepOrder == item.StepOrder && x.Process == item.Process);
                if (step == null)
                {
                    string ProcessStrings = string.Empty;
                    foreach (var processitem in item.Process.Split(ConstantChar.SplitChar))
                    {
                        // 先找有没有这个工序
                        var process = await _processRepository.FindProcessByNoAsync(processitem);
                        Check.NotNull(process, processitem, $"工序:{processitem}不存在");

                        if (string.IsNullOrEmpty(ProcessStrings))
                            ProcessStrings += $"{process.ProcessNo}";
                        else
                            ProcessStrings += $"{ConstantChar.SplitChar}{process.ProcessNo}";
                    }
                    step = await _solutionRepository.InsertSolutionStepAsync(item.StepOrder, ProcessStrings);
                }

                solution.AddStep(step);
            }
            var entity = await _solutionRepository.InsertAsync(solution);
            return await MapToGetOutputDtoAsync(entity);
        }

        public async Task<SolutionDto> GetByNoAsync(string solutionNo)
        {
            var solution = await _solutionRepository.GetSolutionByNoAsync(solutionNo);
            var solutionDto = ObjectMapper.Map<Solution, SolutionDto>(solution);
            return solutionDto;
        }

        public async Task UpdateAsync(SolutionEditDto input)
        {
            var solution = await _solutionRepository.FindAsync(input.Id);
            Check.NotNull(solution, input.SolutionNo, "方案不存在");

            solution.SolutionNo = input.SolutionNo;
            solution.SolutionName = input.SolutionName;
            solution.SolutionSteps = new List<SolutionStep>();
            solution.SolutionStepStrings = string.Empty;
            foreach (var item in input.SolutionSteps)
            {
                var step = await _solutionRepository.GetSolutionStepByNoAsync(item.StepNo);

                if (step == null)
                {
                    string ProcessStrings = string.Empty;
                    foreach (var processitem in item.Process.Split(ConstantChar.SplitChar))
                    {
                        // 先找有没有这个工序
                        var process = await _processRepository.FindProcessByNoAsync(processitem);
                        Check.NotNull(process, processitem, $"工序:{processitem}不存在");

                        if (string.IsNullOrEmpty(ProcessStrings))
                            ProcessStrings += $"{process.ProcessNo}";
                        else
                            ProcessStrings += $"{ConstantChar.SplitChar}{process.ProcessNo}";
                    }
                    step = await _solutionRepository.InsertSolutionStepAsync(item.StepOrder, ProcessStrings);
                }
                else
                {
                    step.StepOrder = item.StepOrder;
                    step.Process = item.Process;
                    step.FinalProcess = item.FinalProcess;
                    step = await _solutionRepository.UpdateSolutionStepAsync(step);
                }

                solution.AddStep(step);
            }
            await _solutionRepository.UpdateAsync(solution);
        }

        public async Task<PagedResultDto<SolutionDto>> GetListBySearchAsync(PagedResultRequestDto input, string? solutionNo)
        {
            await CheckGetListPolicyAsync();

            var query = await CreateFilteredQueryAsync(input);
            query = query.WhereIf(!string.IsNullOrEmpty(solutionNo), x => x.SolutionNo == solutionNo);
            var totalCount = await AsyncExecuter.CountAsync(query);

            query = ApplyPaging(query, input);

            var entities = await AsyncExecuter.ToListAsync(query);
            foreach (var item in entities)
            {
                if (string.IsNullOrEmpty(item.SolutionStepStrings))
                    continue;
                foreach (var solutionStep in item.SolutionStepStrings.Split(ConstantChar.SplitChar))
                {
                    item.SolutionSteps ??= new List<SolutionStep>();
                    item.SolutionSteps.Add(await _solutionStepRepository.GetAsync(Guid.Parse(solutionStep)));
                }
            }
            var entityDtos = await MapToGetListOutputDtosAsync(entities);

            return new PagedResultDto<SolutionDto>(
                totalCount,
                entityDtos
            );
        }
    }
}